import React, { useState, useEffect, useImperativeHandle } from 'react';
import { Icon, message, Form } from 'antd';
import _ from 'lodash';
import { connect } from 'umi';
import FlowCard from './FlowCard';
import PropPanel from './PropPanel';
import styles from './styles.less';
import { NodeUtils, getMockData } from './FlowCard/util.js';

const SCALE_STEP = 5; // 缩放步长

const Process = React.forwardRef(({ tabName, workFlowModel, dispatch }, ref) => {
    const {
        processData,
        processConditions,
        basicData: { scopeGroup }
    } = workFlowModel;

    const [scaleVal, setScaleVal] = useState(100); // 缩放比例，默认100%
    const [verifyMode, setVerifyMode] = useState(false);
    const [updateId, setUpdateId] = useState(0); // key值 用于模拟$forceUpdate
    const [data, setData] = useState(processData || getMockData()); // 流程图数据
    const [activeData, setActiveData] = useState(null); // 被激活的流程卡片数据，用于属性面板编辑

    const forceUpdate = () => {
        setUpdateId(updateId + 1);
    };

    /**
     * 接收所有FlowCard事件触发
     * @param { Object } data - 含有event(事件名称)/args(参数)两个属性
     */
    const eventReciver = ({ event, args }) => {
        if (event === 'edit') {
            setActiveData(args[0]); // 打开属性面板
            return;
        }

        // 本实例只监听了第一层数据（startNode）变动
        // 为了实时更新  采用$forceUpdate刷新 但是由于某些条件下触发失效（未排除清除原因）
        // 使用key + 监听父组件updateId方式强制刷新
        NodeUtils[event](...args);

        // 删除的时候更新条件使用情况
        if (event === 'deleteNode') {
            // 使用状态
            dispatch({
                type: 'workFlowModel/updateCondition',
                payload: { data }
            });
        }

        forceUpdate();
    };

    /**
     * 控制流程图缩放
     * @param { Object } val - 缩放增量 是step的倍数 可正可负
     */
    const changeScale = val => {
        const num = scaleVal + val;
        setScaleVal(num);
        // 缩放介于10%~200%
        if (num <= 10) {
            setScaleVal(10);
        } else if (num >= 200) {
            setScaleVal(200);
        }
    };

    /**
     * 属性面板取消事件
     */
    const onClosePanel = () => {
        setActiveData(null);
    };

    /**
     * 属性面板提交事件
     * @param { Object } value - 被编辑的节点的properties属性对象
     */
    const onPropEditConfirm = (value, content) => {
        const oldProp = activeData.properties;
        const newData = _.cloneDeep(data);
        console.log('右侧输出====>', value);
        const currentNode = NodeUtils.getCurrentNode(activeData.nodeId, newData);
        currentNode.properties = value;
        currentNode.content = content || '请设置条件';

        // 审批节点必须要的字段上移
        if (NodeUtils.isApproverNode(activeData)) {
            currentNode.candidateUsers = value.candidateUsers;
        }
        // 条件节点更新条件使用情况
        if (NodeUtils.isConditionNode(activeData)) {
            // 修改优先级
            if (value.priority !== oldProp.priority || value.isDefault !== oldProp.isDefault) {
                NodeUtils.resortPrioByCNode(currentNode, oldProp.priority, newData);
            }
            // 更改其他条件的文案
            NodeUtils.resetDefaultConditions(currentNode, newData);

            // 使用状态
            dispatch({
                type: 'workFlowModel/updateCondition',
                payload: { data: newData }
            });

            // 更新相关节点的操作权限
            const { isStartNodeChange, isApproveNodeChange } = NodeUtils.updateFormOperate(processConditions, newData);
            message.config({
                maxCount: 2
            });
            if (isStartNodeChange) {
                message.warn('该字段已设置为条件，在发起人节点无法设置为只读或隐藏');
            }
            if (isApproveNodeChange) {
                message.warn('设置为条件后审批人将不能对这个字段进行编辑');
            }

            // console.log('===更新权限后的==>newData', newData);
        }

        setData(newData);
        onClosePanel();
        forceUpdate();
    };

    // 更新card的title
    const updateTCardTitle = (cardData, title) => {
        const newData = _.cloneDeep(data);
        const currentNode = NodeUtils.getCurrentNode(cardData.nodeId, newData);
        currentNode.properties.title = title;
        setData(newData);
    };

    useImperativeHandle(ref, () => ({
        handleUpdate: typeString =>
            new Promise((resolve, reject) => {
                if (typeString === 'hold') {
                    resolve({ formData: data });
                } else {
                    setVerifyMode(true);
                    // 只有开始节点和结束几点的时候不允许提交
                    if (!NodeUtils.checkIntegrity(data)) {
                        // eslint-disable-next-line prefer-promise-reject-errors
                        reject({ tabName, message: '流程定义不完整' });
                    } else if (NodeUtils.checkAllNode(data)) {
                        resolve({ formData: data });
                    } else {
                        // eslint-disable-next-line prefer-promise-reject-errors
                        reject({ tabName });
                    }
                }
            })
    }));

    // 监听model数据变化同步data
    useEffect(() => {
        if (processData && !_.isEqual(data, processData) && _.size(processData) > 1) {
            setData({ ...processData });
        }
    }, [processData]);
    // data变化同步到model
    useEffect(() => {
        if (_.size(data) > 0) {
            dispatch({ type: 'workFlowModel/processDataSave', payload: data });
        }
    }, [data]);

    return (
        <div className={styles.flowContainer}>
            <div className={styles.scaleSlider}>
                <Icon
                    type="minus"
                    className={styles.btn}
                    onClick={() => {
                        changeScale(-SCALE_STEP);
                    }}
                />
                <span style={{ fontSize: 14, width: 35, display: 'inline-block' }}>{scaleVal}%</span>
                <Icon
                    type="plus"
                    className={styles.btn}
                    onClick={() => {
                        changeScale(SCALE_STEP);
                    }}
                />
            </div>

            {data && (
                <FlowCard
                    verifyMode={verifyMode}
                    key={updateId}
                    data={data}
                    updateTCardTitle={updateTCardTitle}
                    onEmits={eventReciver}
                    style={{ transform: `scale(${scaleVal / 100})`, transformOrigin: '50% 0px 0px' }}
                    scopeGroup={scopeGroup}
                />
            )}
            {activeData && (
                <PropPanel data={data} value={activeData} onConfirm={onPropEditConfirm} onCancel={onClosePanel} />
            )}
        </div>
    );
});

export default connect(({ workFlowModel }) => ({ workFlowModel }))(Form.create()(Process));
